package tree.bulid;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * Created by admin on 2019/1/25.
 */
public abstract class TreeBuilderBase<T> {
    public TreeBuilderBase() {
    }

    protected abstract void addChild(T var1, T var2);

    public <TModel, TId> T build(TId rootId, BiConsumer<TModel, TId> setId, Function<TModel, TId> getId, Function<TModel, TId> getPId, Function<TModel, T> toNode, List<TModel> list, Class<TModel> clazz) {
        MapTree mapTree = this.buildMapTree(rootId, setId, getId, getPId, toNode, list, clazz);
        return (T)mapTree.getNode();
    }

    public <TModel, TId> MapTree<TId, T> buildMapTree(TId rootId, BiConsumer<TModel, TId> setId, Function<TModel, TId> getId, Function<TModel, TId> getPId, Function<TModel, T> toNode, List<TModel> list, Class<TModel> clazz) {
        HashMap map = new HashMap();
        list.stream().forEach((x) -> {
            map.put(getId.apply(x), toNode.apply(x));
        });
        Iterator root = list.iterator();

        Object rootItem;
        Object item;
        Object pid;
        while(root.hasNext()) {
            rootItem = root.next();
            Object ex = getPId.apply((TModel) rootItem);
            if(ex != null) {
                item = map.get(ex);
                pid = map.get(getId.apply((TModel)rootItem));
                if(item != null) {
                    this.addChild((T)item,(T)pid);
                }
            }
        }

        Object root1 = null;
        rootItem = null;
        if(rootId == null) {
            try {
                rootItem = clazz.newInstance();
                if(rootId instanceof String) {
                    setId.accept((TModel) rootItem,(TId) "[root]");
                }

                root1 = toNode.apply((TModel) rootItem);
                Iterator ex1 = list.iterator();

                while(ex1.hasNext()) {
                    item = ex1.next();
                    pid = getPId.apply((TModel) item);
                    if(pid == null) {
                        Object sn = map.get(getId.apply((TModel) item));
                        this.addChild((T)root1, (T)sn);
                    }
                }
            } catch (Throwable var15) {
                var15.printStackTrace();
            }
        } else {
            root1 = map.get(rootId);
        }

        return new MapTree(map, root1);
    }
}
